/*
 * Copyright (c) 2011 Nokia Corporation.
 */

#ifndef LEVEL_H
#define LEVEL_H

#include <QObject>
#include <QVector>
#include <QDeclarativeItem>
#include <QFile>
#include <QAudio>
#include <QAudioFormat>

class QAudioOutput;
class QThread;
class SoundPlayer;

/***************************************************************************************************
*Class representing the games level.                                                               *
***************************************************************************************************/
class Level : public QObject
{
    Q_OBJECT
public:
    Level();
    ~Level();
    /***********************************************************************************************
    *load method accessible from QML. Loads the level from xml.                                    *
    ***********************************************************************************************/
    Q_INVOKABLE bool load(QString fileName = "");

    /***********************************************************************************************
    *Objects rowCount property accessible in QML.                                                  *
    ***********************************************************************************************/
    Q_PROPERTY( int rowCount READ rowCount )
    int rowCount() const { return m_rowCount;}

    /***********************************************************************************************
    *Objects columnCount property accessible in QML.                                               *
    ***********************************************************************************************/
    Q_PROPERTY( int columnCount READ columnCount )
    int columnCount() const { return m_columnCount;}

    /***********************************************************************************************
    *item method accessible from QML. Returns a string representing the item at row column.        *
    ***********************************************************************************************/
    Q_INVOKABLE QString item(int row, int column) const;

    /***********************************************************************************************
    *intersects method accessible from QML. Verifies whether the two items intersect.              *
    ***********************************************************************************************/
    Q_INVOKABLE bool intersects(QDeclarativeItem *,QDeclarativeItem *);
    /***********************************************************************************************
    *collidingItems method accessible from QML.                                                    *
    *Goes through the items colliding with the given item, checking their type and calculating the *
    *items intersection if necessary.                                                              *
    *Returns a QVariant containing the list of pointers to QObjects colliding with the item.       *
    ***********************************************************************************************/
    Q_INVOKABLE QVariant collidingItems(QDeclarativeItem *)  const;
    /***********************************************************************************************
    *intersects method accessible from QML. Returns the two items intersection rectangle.          *
    ***********************************************************************************************/
    Q_INVOKABLE QRect intersected(QDeclarativeItem *,QDeclarativeItem *)  const;

    /***********************************************************************************************
    *startBGSound method accessible from QML. Starts the background music.                         *
    ***********************************************************************************************/
    Q_INVOKABLE void startBGSound();
    /***********************************************************************************************
    *playBoing method accessible from QML. Plays the boing sound.                                  *
    ***********************************************************************************************/
    Q_INVOKABLE void playBoing();
    /***********************************************************************************************
    *playGroan method accessible from QML. Plays the groan sound.                                  *
    ***********************************************************************************************/
    Q_INVOKABLE void playGroan();

signals:
    /***********************************************************************************************
    *A signal emitted to request background music playback.                                        *
    ***********************************************************************************************/
    void bgSoundRequest();
    /***********************************************************************************************
    *A signal emitted to request boing sound playback.                                             *
    ***********************************************************************************************/
    void boingSoundRequest();
    /***********************************************************************************************
    *A signal emitted to request groan sound playback.                                             *
    ***********************************************************************************************/
    void groanSoundRequest();
    /***********************************************************************************************
    *A signal emitted to request the player to stop all playback.                                  *
    ***********************************************************************************************/
    void stopSounds();
    /***********************************************************************************************
    *A signal emitted to signalise that it is now safe to quit the application.                    *
    ***********************************************************************************************/
    void readyToQuit();

private:
    /***********************************************************************************************
    *A vector containing strings representing the game boards rows.                                *
    ***********************************************************************************************/
    QVector<QString> m_map;
    /***********************************************************************************************
    *The game boards row and column count.                                                         *
    ***********************************************************************************************/
    int m_rowCount;
    int m_columnCount;

    /***********************************************************************************************
    *The sound player object.                                                                      *
    ***********************************************************************************************/
    SoundPlayer *m_player;
};


/***************************************************************************************************
*Class representing the sound player.                                                              *
***************************************************************************************************/
class SoundPlayer : public QObject
{
    Q_OBJECT
public:
    SoundPlayer();
    ~SoundPlayer();

public slots:
    /***********************************************************************************************
    *Starts the background music.                                                                  *
    ***********************************************************************************************/
    void startBGSound();
    /***********************************************************************************************
    *Plays the boing sound.                                                                        *
    ***********************************************************************************************/
    void playBoing();
    /***********************************************************************************************
    *Plays the groan sound.                                                                        *
    ***********************************************************************************************/
    void playGroan();
    /***********************************************************************************************
    *Stops all playback.                                                                           *
    ***********************************************************************************************/
    void stopSounds();

private slots:
    /***********************************************************************************************
    *A slot called every time a QAudioOutput changes its state.                                    *
    *Resumes background music, cleans the state of the boing and groan sounds.                     *
    ***********************************************************************************************/
    void outputStateChanged(QAudio::State state);

signals:
    /***********************************************************************************************
    *A signal emitted to signalise that all sound playback has now been stopped.                   *
    ***********************************************************************************************/
    void soundsStopped();

private:
    /***********************************************************************************************
    *The sound format used by the player.                                                          *
    ***********************************************************************************************/
    QAudioFormat m_format;

    /***********************************************************************************************
    *Sound outputs.                                                                                *
    ***********************************************************************************************/
    QAudioOutput * m_musicBGOutput;
    QAudioOutput * m_boingOutput;
    QAudioOutput * m_groanOutput;

    /***********************************************************************************************
    *Sound files.                                                                                  *
    ***********************************************************************************************/
    QFile m_musicBGFile;
    QFile m_boingtFile;
    QFile m_groanFile;

    /***********************************************************************************************
    *Flags indicating sound playback.                                                              *
    ***********************************************************************************************/
    bool m_musicBGPlaying;
    bool m_boingPlaying;
    bool m_groanPlaying;
    /***********************************************************************************************
    *A flag indicating if the sound back-end supports the players format.                          *
    ***********************************************************************************************/
    bool m_soundSupport;

    /***********************************************************************************************
    *The sound players dedicated thread.                                                           *
    ***********************************************************************************************/
    QThread *m_soundThread;
};


/***************************************************************************************************
*Class representing an ellipse item used for the games character.                                  *
***************************************************************************************************/
class EllipseItem : public QDeclarativeItem
{
    Q_OBJECT
public:
    EllipseItem(QDeclarativeItem *parent = 0);
    /***********************************************************************************************
    *The ellipse items shape. Returns a painter path containing an ellipse.                        *
    ***********************************************************************************************/
    QPainterPath shape() const;
    /***********************************************************************************************
    *Draws the item.                                                                               *
    ***********************************************************************************************/
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget);

    /***********************************************************************************************
    *Objects margin property accessible in QML.                                                    *
    ***********************************************************************************************/
    Q_PROPERTY(int margin READ margin WRITE setMargin)
    int margin() const { return m_margin;}
    void setMargin(int margin) { m_margin = margin;}

    /***********************************************************************************************
    *Objects burn property accessible in QML.                                                      *
    ***********************************************************************************************/
    Q_PROPERTY(bool burn READ burn WRITE setBurn)
    bool burn() const { return m_burn;}
    void setBurn(bool burn) { m_burn = burn;}

    /***********************************************************************************************
    *A vector containing the rectangles representing intersections with other items.               *
    ***********************************************************************************************/
    QVector<QRect> m_rect;

private:
    /***********************************************************************************************
    *Objects margin value.                                                                         *
    ***********************************************************************************************/
    int m_margin;
    /***********************************************************************************************
    *Objects burn flag.                                                                            *
    ***********************************************************************************************/
    bool m_burn;
};

/***************************************************************************************************
*Class representing a multitouch area, used for game control items(arrows etc.).                   *
***************************************************************************************************/
class MultiTouchItem : public QDeclarativeItem
{
    Q_OBJECT
public:
    MultiTouchItem(QDeclarativeItem *parent = 0);
    /***********************************************************************************************
    *Draws the item.                                                                               *
    ***********************************************************************************************/
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget);
    /***********************************************************************************************
    *Objects source property accessible in QML. Also determines the items pixmap.                  *
    ***********************************************************************************************/
    Q_PROPERTY(QString source READ source WRITE setSource)
    void setSource(const QString &s);
    QString source() const { return m_source; }

protected:
    /***********************************************************************************************
    *A reimplemented sceneEvent method, used to handle touch and mouse press events.               *
    ***********************************************************************************************/
    bool sceneEvent(QEvent *event);

signals:
    /***********************************************************************************************
    *A signal emitted to signalise that the item has been pressed.                                 *
    ***********************************************************************************************/
    void pressed();
    /***********************************************************************************************
    *A signal emitted to signalise that the item has been released.                                *
    ***********************************************************************************************/
    void released();

private:
    /***********************************************************************************************
    *The items source string.                                                                      *
    ***********************************************************************************************/
    QString m_source;
    /***********************************************************************************************
    *The items pixmap.                                                                             *
    ***********************************************************************************************/
    QPixmap m_pixmap;
};

#endif // LEVEL_H
